#include <referee.h>

namespace dji {
void DjiReferee::Receive(std::uint8_t* rxBuffer, std::uint16_t len) {
    using namespace ref_type;
    auto* header = reinterpret_cast<FrameHeader*>(rxBuffer);
    uint8_t* begin = rxBuffer, pkg_cnt = 0;
    while (header->SOF == 0xA5 && rxBuffer - begin <= len) {
        pkg_cnt++;
        auto* cmd_id = reinterpret_cast<uint16_t*>(rxBuffer + sizeof(FrameHeader));
        // if (header->DataLength + sizeof(FrameTemplate<void>) != len) {
        //     return;
        // } 2025/3/25 空闲中断，电管会一次发好几帧。
        if (CRCLib::Calculate(rxBuffer, sizeof(FrameHeader) - 1, kCrC8Table, static_cast<uint8_t>(0xFF)) !=
            header->CRC8) {
            return;
        }

        switch (*cmd_id) {
            case kGameStatus:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kGameStatus>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kGameStatus>>*>(rxBuffer))->Tail) {
                    gameStatus_ = (reinterpret_cast<FrameTemplate<DataType<kGameStatus>>*>(rxBuffer))->Data;
                }
                break;
            case kGameResult:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kGameResult>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kGameResult>>*>(rxBuffer))->Tail) {
                    gameResult_ = (reinterpret_cast<FrameTemplate<DataType<kGameResult>>*>(rxBuffer))->Data;
                }
                break;
            case kRobotHp:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRobotHp>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRobotHp>>*>(rxBuffer))->Tail) {
                    robotHp_ = (reinterpret_cast<FrameTemplate<DataType<kRobotHp>>*>(rxBuffer))->Data;
                }
                break;
            case kFieldEvent:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kFieldEvent>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kFieldEvent>>*>(rxBuffer))->Tail) {
                    fieldEvent_ = (reinterpret_cast<FrameTemplate<DataType<kFieldEvent>>*>(rxBuffer))->Data;
                }
                break;
            case kSupply:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kSupply>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kSupply>>*>(rxBuffer))->Tail) {
                    supply_ = (reinterpret_cast<FrameTemplate<DataType<kSupply>>*>(rxBuffer))->Data;
                }
                break;
            case kWarning:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kWarning>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kWarning>>*>(rxBuffer))->Tail) {
                    warning_ = (reinterpret_cast<FrameTemplate<DataType<kWarning>>*>(rxBuffer))->Data;
                }
                break;
            case kDart:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kDart>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kDart>>*>(rxBuffer))->Tail) {
                    dart_ = (reinterpret_cast<FrameTemplate<DataType<kDart>>*>(rxBuffer))->Data;
                }
                break;
            case kRobotPerf:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRobotPerf>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRobotPerf>>*>(rxBuffer))->Tail) {
                    robotPerf_ = (reinterpret_cast<FrameTemplate<DataType<kRobotPerf>>*>(rxBuffer))->Data;
                }
                break;
            case kPowerAndHeat:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kPowerAndHeat>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kPowerAndHeat>>*>(rxBuffer))->Tail) {
                    powerAndHeat_ = (reinterpret_cast<FrameTemplate<DataType<kPowerAndHeat>>*>(rxBuffer))->Data;
                }
                break;
            case kRobotPos:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRobotPos>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRobotPos>>*>(rxBuffer))->Tail) {
                    robotPos_ = (reinterpret_cast<FrameTemplate<DataType<kRobotPos>>*>(rxBuffer))->Data;
                }
                break;
            case kRobotGain:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRobotGain>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRobotGain>>*>(rxBuffer))->Tail) {
                    robotGain_ = (reinterpret_cast<FrameTemplate<DataType<kRobotGain>>*>(rxBuffer))->Data;
                }
                break;
            case kAirSupport:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kAirSupport>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kAirSupport>>*>(rxBuffer))->Tail) {
                    airSupport_ = (reinterpret_cast<FrameTemplate<DataType<kAirSupport>>*>(rxBuffer))->Data;
                }
                break;
            case kDamageStatus:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kDamageStatus>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kDamageStatus>>*>(rxBuffer))->Tail) {
                    damageStatus_ = (reinterpret_cast<FrameTemplate<DataType<kDamageStatus>>*>(rxBuffer))->Data;
                }
                break;
            case kShootStatus:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kShootStatus>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kShootStatus>>*>(rxBuffer))->Tail) {
                    shootStatus_ = (reinterpret_cast<FrameTemplate<DataType<kShootStatus>>*>(rxBuffer))->Data;
                }
                break;
            case kRemainProjectile:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRemainProjectile>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRemainProjectile>>*>(rxBuffer))->Tail) {
                    remainProjectile_ = (reinterpret_cast<FrameTemplate<DataType<kRemainProjectile>>*>(rxBuffer))->Data;
                }
                break;
            case kRFIDStatus:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRFIDStatus>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRFIDStatus>>*>(rxBuffer))->Tail) {
                    rfidStatus_ = (reinterpret_cast<FrameTemplate<DataType<kRFIDStatus>>*>(rxBuffer))->Data;
                }
                break;
            case kDartCmd:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kDartCmd>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kDartCmd>>*>(rxBuffer))->Tail) {
                    dartCmd_ = (reinterpret_cast<FrameTemplate<DataType<kDartCmd>>*>(rxBuffer))->Data;
                }
                break;
            case kGroundPos:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kGroundPos>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kGroundPos>>*>(rxBuffer))->Tail) {
                    groundPos_ = (reinterpret_cast<FrameTemplate<DataType<kGroundPos>>*>(rxBuffer))->Data;
                }
                break;
            case kRadarMark:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRadarMark>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRadarMark>>*>(rxBuffer))->Tail) {
                    radarMark_ = (reinterpret_cast<FrameTemplate<DataType<kRadarMark>>*>(rxBuffer))->Data;
                }
                break;
            case kSentryDec:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kSentryDec>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kSentryDec>>*>(rxBuffer))->Tail) {
                    sentryDec_ = (reinterpret_cast<FrameTemplate<DataType<kSentryDec>>*>(rxBuffer))->Data;
                }
                break;
            case kRadarDec:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRadarDec>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRadarDec>>*>(rxBuffer))->Tail) {
                    radarDec_ = (reinterpret_cast<FrameTemplate<DataType<kRadarDec>>*>(rxBuffer))->Data;
                }
                break;
            case kMapInteraction:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kMapInteraction>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kMapInteraction>>*>(rxBuffer))->Tail) {
                    mapInteraction_ = (reinterpret_cast<FrameTemplate<DataType<kMapInteraction>>*>(rxBuffer))->Data;
                }
                break;
            case kKeyMouseCtrl:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kKeyMouseCtrl>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kKeyMouseCtrl>>*>(rxBuffer))->Tail) {
                    keyMouseCtrl_ = (reinterpret_cast<FrameTemplate<DataType<kKeyMouseCtrl>>*>(rxBuffer))->Data;
                }
                break;
            case kRadarData:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kRadarData>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kRadarData>>*>(rxBuffer))->Tail) {
                    radarData_ = (reinterpret_cast<FrameTemplate<DataType<kRadarData>>*>(rxBuffer))->Data;
                }
                break;
            case kCustomCtrl:
                if (CRCLib::Calculate(rxBuffer, sizeof(FrameTemplate<DataType<kCustomCtrl>>) - 2, kCRC16Table) ==
                    (reinterpret_cast<FrameTemplate<DataType<kCustomCtrl>>*>(rxBuffer))->Tail) {
                    customCtrl_ = (reinterpret_cast<FrameTemplate<DataType<kCustomCtrl>>*>(rxBuffer))->Data;
                }
            case kSentryData:
            case kMapData:
            case kInteraction:
            case kCustomCtrlNoUsed:
            default:
                break;
        }
        rxBuffer += header->DataLength + sizeof(FrameTemplate<void>);
        header = reinterpret_cast<FrameHeader*>(rxBuffer);
    }
}
} // namespace dji